library(tidyverse)
library(eph)
library(spatstat)
options(scipen = 9999) #la opción scipen modifica el límite en el que los números decimales pasan a expresarse con notación científica. En este caso, lo utilizamos para evitar la notación científica.
options(dplyr.summarise.inform = FALSE)

Introducción

En la clase de hoy vamos a explorar nuevas formas de procesar una base de datos y visualizar nuestros resultados.

En particular, vamos a introducir el paquete plotly para generar visualizaciones interactivas.

Por último, vamos a trabajar con funciones e iteraciones para escalar nuestra capacidad de análisis de datos y presentación de resultados.

Visualización interactiva

La visualización interactiva va a permitir que los usuarios de nuestras visualizaciones puedan explorar nuestros resultados con mayor libertad. Es decir, van a permitir que cada usuario pueda analizar con mayor detalle lo que más le interesa.

Vamos a volver a trabajar con la base de EPH para encontrar la brecha salarial entre varones y mujeres para cada sector productivo, y luego vamos a graficarlo interactivamente.

base <- eph::get_microdata(year = 2019, 
                            trimester = 1,
                            type = "individual", 
                            destfile = "./eph_2019_T1.rds")  %>% 
  organize_caes()%>%  #recodifica la variable que indica el sector de la ocupación
  select(ESTADO,"SEXO" = CH04, "Ing_Ocup_Principal"= P21, PONDIIO,caes_eph_label, "Horas" = PP3E_TOT, PONDERA) %>% 
  
  mutate(ESTADO = case_when(ESTADO == 1 ~ "Ocupado",
                            ESTADO == 2 ~ "Desocupado",
                            ESTADO == 3 ~ "Inactivo",
                            ESTADO == 4 ~ "Menor de 10 años"),
         SEXO = case_when(SEXO == 1 ~ "Varones",
                          SEXO == 2 ~ "Mujeres")) %>% 
  filter(Ing_Ocup_Principal != -9) %>%  #excluimos el valor de no respuesta
  filter(ESTADO == "Ocupado")

Calculamos el ingreso medio de los trabajadores de cada sexo y sector, y luego la brecha. También vamos a tener en cuenta en qué sectores las mujeres tienen una participación mayor.

#Aclaración: el ponderador para la variable de ingreso de la ocupación proncipal es PONDIIO

ingresos <- base %>% 
  filter(Ing_Ocup_Principal > 0) %>% #excluimos a personas con ingreso = 0
  group_by(SEXO,caes_eph_label) %>% 
  summarise(Ingreso_medio = weighted.mean(Ing_Ocup_Principal,PONDIIO, na.rm = T)) %>% #al igual que en otras funciones, en este caso na.rm excluye los valores faltantes del promedio ponderado
  pivot_wider(id_cols = caes_eph_label, names_from = SEXO, values_from = Ingreso_medio) %>% 
  mutate(brecha =  ((Varones-Mujeres)/Varones))

ingresos
## # A tibble: 14 × 4
##    caes_eph_label                                      Mujeres Varones  brecha
##    <fct>                                                 <dbl>   <dbl>   <dbl>
##  1 Actividades primarias                                26607.  38218.  0.304 
##  2 Industria manufacturera                              15351.  23005.  0.333 
##  3 Construccion                                         17316.  15654. -0.106 
##  4 Comercio                                             14916.  20068.  0.257 
##  5 Hoteles y restaurantes                               11952.  15263.  0.217 
##  6 Transporte, almacenamiento y comunicaciones          24106.  26564.  0.0925
##  7 Servicios financieros, de alquiler y empresariales   23430.  27491.  0.148 
##  8 Administracion publica, defensa y seguridad social   25803.  27890.  0.0748
##  9 Ensenanza                                            19573.  22295.  0.122 
## 10 Servicios sociales y de salud                        24354.  34723.  0.299 
## 11 Servicio domestico                                    6844.   5779. -0.184 
## 12 Otros servicios comunitarios, sociales y personales  10810.  20931.  0.484 
## 13 Otras ramas                                          29610.  26477. -0.118 
## 14 Actividades no bien especificadas                    23731.  28258.  0.160
feminizacion <-  base %>% 
  group_by(SEXO,caes_eph_label) %>%
  summarise(Casos = sum(PONDERA)) %>% 
  ungroup() %>% 
  group_by(caes_eph_label) %>% 
  mutate(Total = sum(Casos),
         feminizacion = (Casos/Total)*100) %>% 
  filter(SEXO == "Mujeres") %>% 
  select(caes_eph_label, feminizacion)

feminizacion
## # A tibble: 14 × 2
## # Groups:   caes_eph_label [14]
##    caes_eph_label                                      feminizacion
##    <fct>                                                      <dbl>
##  1 Actividades primarias                                      14.6 
##  2 Industria manufacturera                                    30.8 
##  3 Construccion                                                2.73
##  4 Comercio                                                   41.6 
##  5 Hoteles y restaurantes                                     45.8 
##  6 Transporte, almacenamiento y comunicaciones                14.5 
##  7 Servicios financieros, de alquiler y empresariales         42.5 
##  8 Administracion publica, defensa y seguridad social         41.6 
##  9 Ensenanza                                                  75.9 
## 10 Servicios sociales y de salud                              66.5 
## 11 Servicio domestico                                         96.4 
## 12 Otros servicios comunitarios, sociales y personales        44.1 
## 13 Otras ramas                                                16.8 
## 14 Actividades no bien especificadas                          23.2
ingresos <- ingresos %>% 
  left_join(.,feminizacion, by = "caes_eph_label")

ingresos
## # A tibble: 14 × 5
##    caes_eph_label                                Mujeres Varones  brecha femin…¹
##    <fct>                                           <dbl>   <dbl>   <dbl>   <dbl>
##  1 Actividades primarias                          26607.  38218.  0.304    14.6 
##  2 Industria manufacturera                        15351.  23005.  0.333    30.8 
##  3 Construccion                                   17316.  15654. -0.106     2.73
##  4 Comercio                                       14916.  20068.  0.257    41.6 
##  5 Hoteles y restaurantes                         11952.  15263.  0.217    45.8 
##  6 Transporte, almacenamiento y comunicaciones    24106.  26564.  0.0925   14.5 
##  7 Servicios financieros, de alquiler y empresa…  23430.  27491.  0.148    42.5 
##  8 Administracion publica, defensa y seguridad …  25803.  27890.  0.0748   41.6 
##  9 Ensenanza                                      19573.  22295.  0.122    75.9 
## 10 Servicios sociales y de salud                  24354.  34723.  0.299    66.5 
## 11 Servicio domestico                              6844.   5779. -0.184    96.4 
## 12 Otros servicios comunitarios, sociales y per…  10810.  20931.  0.484    44.1 
## 13 Otras ramas                                    29610.  26477. -0.118    16.8 
## 14 Actividades no bien especificadas              23731.  28258.  0.160    23.2 
## # … with abbreviated variable name ¹​feminizacion

Tal como se refleja en nuestros resultados, las brechas de ingresos tienden a estar a favor de los varones. No obstante, es interesante vincular este análisis con la tasa de feminización para interpretar casos como el del sector de la Construcción, donde la mayor parte de los trabajadores son varones, pero las mujeres participan en roles que requieren una mayor calificación (trabajo de oficina, arquitectas, etc.): esto tiene como resultado una brecha de ingresos a favor de las mujeres.

plotly

Para graficar nuestros resultados, vamos a recurrir al paquete plotly. Este paquete nos ayuda a crear gráficos interactivos (y puede utilizarse en combinación con ggplot para transformar un gráfico no interactivo en un gráfico interactivo).

library(plotly)

En nuestro gráfico, vamos a graficar el ingreso medio de cada sector productivo para trabajadores de cada sexo, coloreando cada burbuja de acuerdo con la magnitud de la brecha, y determinando el tamaño de la burbuja según la proporción de trabajadoras mujeres en el sector.

#La sintaxis es un poco distinta a la de ggplot, más abajo podemos ver cómo recurrir a ella si nos resulto más cómoda

plot_ly(ingresos, x = ~Mujeres, y = ~Varones, 
        color = ~brecha, colors = 'Spectral',
        type = 'scatter', mode = 'markers',  marker = list(size = ~feminizacion, opacity = 0.9),
        
        hoverinfo = 'text',
        text = ~paste(caes_eph_label, '<br>Mujeres:', paste0("$",round(Mujeres,1)), '<br>Varones:', paste0("$",round(Varones,1)), '<br>Brecha:', paste0(round(brecha*100,1), "%"), '<br>Proporción de trabajadoras mujeres:', paste0(round(feminizacion,1), "%"))
        
        ) %>% 
       layout(title = 'Ingreso medio y brecha salarial por sector productivo',
         xaxis = list(showgrid = FALSE),
         yaxis = list(showgrid = FALSE),
         font = list(family ="Times New Roman"))

Prueben pasar el mouse por encima del gráfico, moverlo, hacer zoom, etc.

¿Qué análisis podemos hacer de la información representada?

ggplotly()

La función ggplotly() convierte nuestros ggplots en plotly. De esta forma, podemos tomar cualquiera de las visualizaciones que aprendimos a hacer la clase pasada y hacerla interactiva.

Por ejemplo:

feminizacion <-  base %>% 
  group_by(SEXO,caes_eph_label) %>%
  summarise(Casos = sum(PONDERA)) %>% 
  ungroup() %>% 
  group_by(caes_eph_label) %>% 
  mutate(Total = sum(Casos),
         feminizacion = (Casos/Total)*100)%>% 
  filter(SEXO == "Mujeres") %>% 
  select(caes_eph_label, feminizacion)


feminizacion
## # A tibble: 14 × 2
## # Groups:   caes_eph_label [14]
##    caes_eph_label                                      feminizacion
##    <fct>                                                      <dbl>
##  1 Actividades primarias                                      14.6 
##  2 Industria manufacturera                                    30.8 
##  3 Construccion                                                2.73
##  4 Comercio                                                   41.6 
##  5 Hoteles y restaurantes                                     45.8 
##  6 Transporte, almacenamiento y comunicaciones                14.5 
##  7 Servicios financieros, de alquiler y empresariales         42.5 
##  8 Administracion publica, defensa y seguridad social         41.6 
##  9 Ensenanza                                                  75.9 
## 10 Servicios sociales y de salud                              66.5 
## 11 Servicio domestico                                         96.4 
## 12 Otros servicios comunitarios, sociales y personales        44.1 
## 13 Otras ramas                                                16.8 
## 14 Actividades no bien especificadas                          23.2
#paleta de colores divina!
library(wesanderson)


plot_estatico <- feminizacion %>% 
  ggplot(.,aes(x = fct_reorder(caes_eph_label,feminizacion), y = feminizacion, 
        fill = feminizacion,
        #para que el hovertext nos quede como queremos en el siguiente paso 
        text = paste(caes_eph_label, '<br>Proporción de trabajadoras mujeres:', paste0(round(feminizacion,1), "%"))
  )
        )+
  geom_col(alpha = 0.9)+
  theme_minimal()+
  coord_flip()+
  labs(title = 'Tasa de feminización de las ramas de actividad',
       x="",y="")+
  scale_y_continuous(labels = function(x) paste0(x,"%"))+
  scale_x_discrete(labels = function(x) str_wrap(x,25))+
  scale_fill_gradientn(colours = wes_palette("Zissou1", 100, type = "continuous")) +
  guides(fill = "none")


plot_estatico

#lo hacemos interactivo

ggplotly(plot_estatico, 
         tooltip = "text") %>% 
  layout(font = list(family ="Times New Roman"))

Iteración y funciones

La iteración y las funciones nos van a permitir reducir la duplicación en el código (copiar y pegar las mismas instrucciones).

¿Por qué reducir la duplicación?

  • Es más fácil entender tu código (para vos en otro momento, o para un tercero).

  • Es más simple realizar cambios y encontrar errores.

Además, van a potenciar nuestro trabajo con R, permitiéndonos escalar la cantidad de procesamientos y visualizaciones que podemos obtener a partir del análisis de una base de datos en muy poco tiempo.

Iteraciones

La iteración es una herramienta para repetir la misma tarea con múltiples inputs (variables, conjuntos de datos, etc.).

Un loop es una estructura de código que nos permite aplicar iterativamente un mismo conjunto de comandos, variando el valor de una variable. Su estructura general es la siguiente:

for (variable in vector) {
  #Operaciones
}

El nombre que definamos para la variable debe ser el mismo que utilicemos para realizar las operaciones dentro del loop, pero puede ser cualquiera (x,i,planta,supercalifragil, etc).

Por ejemplo:

for (x in 1:5) {
  print(x*x)
}
## [1] 1
## [1] 4
## [1] 9
## [1] 16
## [1] 25

Lo que hizo el código fue crear una variable x, que fue tomando los valores 1, 2, 3, 4 y 5, y en cada caso multiplicándose por sí misma.

En nuestro loop pueden intervenir también objetos que hayamos definido previamente.

Por ejemplo:

b <- 10

for (x in 1:5) {
  print(x+b)
}
## [1] 11
## [1] 12
## [1] 13
## [1] 14
## [1] 15

Una herramienta que vamos a utilizar mucho es la función seq(), que permite generar una secuencia de números (que vamos a utilizar para iterar). Por default, si ingresamos un único número como argumento, genera una secuencia desde 1 hasta ese número.

seq(3)
## [1] 1 2 3
for (i in (seq(3))) {
  print(i)
}
## [1] 1
## [1] 2
## [1] 3

¿Cuándo podríamos usar esto? En operaciones de subsetting o slicing

#defino el vector
vec <- c("a","b","c")


#¿cuántos elementos tiene?
length(vec)
## [1] 3
#Convierto cada elemento al mismo elemento en mayúscula
for (letra in (seq(length(vec)))) {
  vec[letra] <- toupper(vec[letra])
}

#¿Cómo quedó?
vec
## [1] "A" "B" "C"

¿Qué pasó? Nuestro loop fue avanzando sobre los elementos de vec, reemplazándolos por el mismo valor en mayúscula. Por ejemplo, al vec[1] = “a”, lo transformó en “A”.

Aplicación sobre una base de datos

Veamos cómo puede ser útil para un procesamiento.

Si tenemos una base de datos con información sobre distintos tipos de población, podemos querer generar una medida resumen para cada segmento de la población.

Por ejemplo, supongamos que queremos llevar a cabo un análisis más detallado de la distribución de los ingresos por sexo para cada rama de actividad:

vector_valores <- unique(base$caes_eph_label)

#En esta lista vamos a guardar nuestros resultados
resultados <- list()

for (valor in (seq(length(vector_valores)))) {
  
  tabla_resumen <- base %>% 
    filter(caes_eph_label == vector_valores[valor]) %>% 
    filter(Ing_Ocup_Principal > 0) %>% 
    group_by(SEXO) %>% 
    summarise(sector = unique(caes_eph_label),
              max_ing = max(Ing_Ocup_Principal, na.rm = T),
              min_ing = min(Ing_Ocup_Principal, na.rm = T),
              media_ing = weighted.mean(Ing_Ocup_Principal, PONDIIO, na.rm = T),
              mediana_ing = weighted.median(Ing_Ocup_Principal, PONDIIO, na.rm = T))
  
  resultados[[valor]] <-  tabla_resumen
  
  #En este caso, estamos usando “valor” como iterador, en el sentido de índice dentro de un vector (vector_valores). Si en cada iteración, además de nuestro procesamiento imprimos "valor", obtenemos la serie de índices.
  
  print(valor)
  
  #Es decir, no estamos recurriendo directamente a cada uno de los valores del vector, sino que cada sector se corresponde con uno de estos índices. Los podemos obtener (por ejemplo) así:
  
  print(unique(as.character(tabla_resumen$sector)))
  
  #Al iterar, print puede ser muy útil para entender qué está pasando (especialmente si los resultados no son los que esperamos!).
  
}
## [1] 1
## [1] "Actividades primarias"
## [1] 2
## [1] "Construccion"
## [1] 3
## [1] "Servicios financieros, de alquiler y empresariales"
## [1] 4
## [1] "Transporte, almacenamiento y comunicaciones"
## [1] 5
## [1] "Ensenanza"
## [1] 6
## [1] "Administracion publica, defensa y seguridad social"
## [1] 7
## [1] "Comercio"
## [1] 8
## [1] "Servicio domestico"
## [1] 9
## [1] "Industria manufacturera"
## [1] 10
## [1] "Hoteles y restaurantes"
## [1] 11
## [1] "Otros servicios comunitarios, sociales y personales"
## [1] 12
## [1] "Servicios sociales y de salud"
## [1] 13
## [1] "Otras ramas"
## [1] 14
## [1] "Actividades no bien especificadas"
#Veamos una de las tablas que generamos:

resultados[[3]]
## # A tibble: 2 × 6
##   SEXO    sector                                 max_ing min_ing media…¹ media…²
##   <chr>   <fct>                                    <int>   <int>   <dbl>   <dbl>
## 1 Mujeres Servicios financieros, de alquiler y …  100000     450  23430.   19950
## 2 Varones Servicios financieros, de alquiler y …  300000     300  27491.   21750
## # … with abbreviated variable names ¹​media_ing, ²​mediana_ing

También podemos presentar nuestros resultados de una manera más amigable con quien está leyendo, o listo para copiar e incluir en un informe:

for (valor in (seq(length(vector_valores)))) {
  
  print(paste0("Para el sector ", unique(resultados[[valor]]$sector), ", el ingreso máximo alcanzado por un varón fue de $", resultados[[valor]]$max_ing[resultados[[valor]]$SEXO == "Varones"], ". Para las mujeres, por otro lado, fue de $", resultados[[valor]]$max_ing[resultados[[valor]]$SEXO == "Mujeres"]))
  
  
}
## [1] "Para el sector Actividades primarias, el ingreso máximo alcanzado por un varón fue de $250000. Para las mujeres, por otro lado, fue de $80000"
## [1] "Para el sector Construccion, el ingreso máximo alcanzado por un varón fue de $200000. Para las mujeres, por otro lado, fue de $75000"
## [1] "Para el sector Servicios financieros, de alquiler y empresariales, el ingreso máximo alcanzado por un varón fue de $300000. Para las mujeres, por otro lado, fue de $100000"
## [1] "Para el sector Transporte, almacenamiento y comunicaciones, el ingreso máximo alcanzado por un varón fue de $290000. Para las mujeres, por otro lado, fue de $70000"
## [1] "Para el sector Ensenanza, el ingreso máximo alcanzado por un varón fue de $100000. Para las mujeres, por otro lado, fue de $70000"
## [1] "Para el sector Administracion publica, defensa y seguridad social, el ingreso máximo alcanzado por un varón fue de $150000. Para las mujeres, por otro lado, fue de $200000"
## [1] "Para el sector Comercio, el ingreso máximo alcanzado por un varón fue de $300000. Para las mujeres, por otro lado, fue de $100000"
## [1] "Para el sector Servicio domestico, el ingreso máximo alcanzado por un varón fue de $15000. Para las mujeres, por otro lado, fue de $40500"
## [1] "Para el sector Industria manufacturera, el ingreso máximo alcanzado por un varón fue de $200000. Para las mujeres, por otro lado, fue de $200000"
## [1] "Para el sector Hoteles y restaurantes, el ingreso máximo alcanzado por un varón fue de $60000. Para las mujeres, por otro lado, fue de $35000"
## [1] "Para el sector Otros servicios comunitarios, sociales y personales, el ingreso máximo alcanzado por un varón fue de $250000. Para las mujeres, por otro lado, fue de $80000"
## [1] "Para el sector Servicios sociales y de salud, el ingreso máximo alcanzado por un varón fue de $390000. Para las mujeres, por otro lado, fue de $150000"
## [1] "Para el sector Otras ramas, el ingreso máximo alcanzado por un varón fue de $70000. Para las mujeres, por otro lado, fue de $60000"
## [1] "Para el sector Actividades no bien especificadas, el ingreso máximo alcanzado por un varón fue de $100000. Para las mujeres, por otro lado, fue de $80000"

Funciones

Retomamos lo introducido en la clase 2: la función es una forma de encapsular una serie de operaciones a las que vayamos a recurrir más de una vez, esta es su estructura general:

fun_ej <-function(argumentos){
    #[se hace algún cómputo]
}

En este caso, vamos a utilizar esta herramienta -en conjunto con la iteración- para generar una serie de gráficos donde se visualice la distribución de los ingresos de las mujeres y los varones que se desempeñan en cada sector productivo de acuerdo con las horas que trabajan por semana.

Primero, vamos a generar los datos que vamos a graficar:

vector_valores <- unique(base$caes_eph_label)

#En esta lista vamos a guardar nuestros resultados
datos_graf <- list()

for (valor in (seq(length(vector_valores)))) {
  
  tabla_resumen <- base %>% 
    filter(caes_eph_label == vector_valores[valor]) %>% 
    filter(Ing_Ocup_Principal > 0) %>% 
     filter(Horas > 0) %>% 
    filter(Horas != 999) %>% 
    group_by(SEXO, Ing_Ocup_Principal, Horas) %>% 
    summarise(Casos = sum(PONDIIO, na.rm = T),
              sector = unique(caes_eph_label)) 
  
  #print(head(tabla_resumen,5))
  
  datos_graf[[valor]] <-  tabla_resumen
  
}

Veamos cómo queda algún elemento:

datos_graf[[2]]
## # A tibble: 688 × 5
## # Groups:   SEXO, Ing_Ocup_Principal [150]
##    SEXO    Ing_Ocup_Principal Horas Casos sector      
##    <chr>                <int> <int> <int> <fct>       
##  1 Mujeres               2000     3  2107 Construccion
##  2 Mujeres               3000    20   269 Construccion
##  3 Mujeres               3500    25    25 Construccion
##  4 Mujeres               4000    40   141 Construccion
##  5 Mujeres               5000     8   391 Construccion
##  6 Mujeres               5000    10   654 Construccion
##  7 Mujeres               6000     8    37 Construccion
##  8 Mujeres               6400    15   268 Construccion
##  9 Mujeres               6500    15   290 Construccion
## 10 Mujeres              10000    30  1571 Construccion
## # … with 678 more rows

Luego, creamos nuestra función que grafica la información de una tabla:

crear_grafico = function(tabla){
  
  ggplot(tabla, aes(x = Horas, y = Ing_Ocup_Principal, size =Casos, color = SEXO)) +
        geom_point(alpha = 0.4)+
        theme_minimal()+
        scale_color_manual(values = c("deeppink4","mediumseagreen"))+
         scale_size_continuous(range = c(2, 15))+
        scale_y_continuous(labels = function(x) paste0("$",x))+
        facet_wrap(~SEXO, scales = "fixed", nrow = 1)+
        labs(title = unique(tabla$sector),
             y = "Ingreso de la ocupación principal",
             x = "Horas semanales trabajadas",
             color = "Sexo")+
        theme(legend.position = "bottom")
  
    ggsave(paste0("./graficos/",tolower(str_replace_all(unique(tabla$sector), " ", "_")),".png"), bg = "white")
  
}

Finalmente, la aplicamos de forma iterativa:

for (i in seq(length(datos_graf))) {
  
  crear_grafico(datos_graf[[i]])
  
}

Los resultados de nuestro procesamiento están guardados en la carpeta graficos de la clase 6.

¡Terminamos! Ahora, vamos a la parte práctica.